package com.ale.oxetool.model;

import com.ale.oxetool.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * Created by guoshunw on 2016/4/6.
 */
public class BatchSwitchTask {

    private String oxe1Host;
    private String oxe2Host;

    public void setOxe1Host(String oxe1Host) {
        this.oxe1Host = oxe1Host;
    }

    public void setOxe2Host(String oxe2Host) {
        this.oxe2Host = oxe2Host;
    }

    private List<SwitchTask> tasks = new ArrayList<SwitchTask>();
    private String desc;

    private static Logger log = LoggerFactory.getLogger(BatchSwitchTask.class);
    //the last status modified time in this batch task
    private AtomicLong lastModified = new AtomicLong(System.currentTimeMillis());

    public List<SwitchTask> getTasks() {
        return tasks;
    }

    public void getOrWaitTask(long lastModified) {

        log.debug("Thread {} successfully get task list.", Thread.currentThread().getName());
    }

    public List<SwitchTask> getStatusTasks(int status) {
        // find the restart in progress phone
        return tasks.stream().filter(task -> task.getStatus() == status
        ).collect(Collectors.toList());
    }

    public String getDesc() {
        return desc;
    }

    public void addTask(SwitchTask task) {
        task.setBatch(this);
        this.tasks.add(task);
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public boolean isCompleted() {
        return tasks.stream().allMatch(task -> Arrays.asList(SwitchTask.DONE, SwitchTask.TIMEOUT, SwitchTask.FAIL).contains(task.getStatus()));
    }

    public void updateCurrentStatus() {
        long currentStamp = System.currentTimeMillis();
        this.lastModified.set(currentStamp);
        log.debug("Status updated by thread {} at {}", Thread.currentThread().getName(), currentStamp);
    }

    /**
     * Update current task status by the latest phone info
     * and return done tasks
     */
    public synchronized List<SwitchTask> updateSwitchStatus(List<Phone> latestPhones, Util util) {
        List<SwitchTask> doneTasks = new ArrayList<>();

        for (Phone phone : latestPhones) {
            for (SwitchTask task : tasks) {
                if (phone.getMac().equals(task.getPhone().getMac())) { // the same phone
                    String targetPlatform = task.getTargetPlatform().replaceAll("^0+", "");
                    String targetOXEHost = targetPlatform.equals("1") ? oxe1Host : oxe2Host;
//                    String otherOXEHost = targetPlatform.equals("1") ? oxe2Host : oxe1Host;

                    if (phone.getOxeServerAddr().equals(targetOXEHost)) {
                        task.setStatus(SwitchTask.DONE);
                        doneTasks.add(task);
                    }
                    /*
                        Find a way to detect the state that phone on the original oxe server after reset

                        @see: SwitchTaskServiceImpl.java
                        The following method not work because the SwitchTaskWorker and SwitchRefreshTaskWorker were started at the
                        same time.

                        The switch task status may changed by the SwitchTaskWorker thread just after the SwitchRefreshTaskWorker obtain the phones
                        from phoneServer. This would cause phone oxe is still the original, but the task status is no more NOT_START.
                        So we try to find if this occurred twice
                    */
                    else if (task.getStatus() != SwitchTask.NOT_START) {
                        log.warn("Task already started, but phone oxe address back to original oxe, set task status to fail." +
                                "task.status={}, phone.oxeserver={}", task.getStatus(), phone.getOxeServerAddr());
//                        if (task.getExceptionStatusCounter() > 0) {
//                            task.setStatus(SwitchTask.FAIL);
//                        } else {
//                            task.setExceptionStatusCounter(task.getExceptionStatusCounter() + 1);
//                        }
                    }
                }
            }
        }
        return doneTasks;
    }

    public int size() {
        return this.tasks.size();
    }

    public long getLastModified() {
        return lastModified.get();
    }
}
